package librus.pdf
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.filesystem.File;
	import flash.filesystem.FileMode;
	import flash.filesystem.FileStream;
	import flash.geom.Rectangle;
	import flash.utils.ByteArray;
	
	import librus.control.ProgressManager;
	import librus.model.Card;
	
	import org.alivepdf.display.Display;
	import org.alivepdf.images.ColorSpace;
	import org.alivepdf.layout.Layout;
	import org.alivepdf.layout.Orientation;
	import org.alivepdf.layout.Size;
	import org.alivepdf.layout.Unit;
	import org.alivepdf.pages.Page;
	import org.alivepdf.pdf.PDF;
	import org.alivepdf.saving.Method;

	public class PdfManager extends EventDispatcher
	{
		public static const FILL_COMPLETE:String = "fillComplete";
		
		public function PdfManager(progress:ProgressManager)
		{
			__progress = progress;
			
			__pdf = new org.alivepdf.pdf.PDF( Orientation.PORTRAIT, Unit.MM,true, Size.A4 );
			__pdf.setMargins(0,0,0,0);
			__pdf.setDisplayMode( Display.FULL_PAGE, Layout.SINGLE_PAGE);
		}
		
		private var __pdf:org.alivepdf.pdf.PDF;
		
		private var __dpi:Number;
		private var __cardWidth:Number;
		private var __cardHeight:Number;
		private var __contentRectangle:Rectangle;
		
		private var __index:int;
		private var __count:int;
		private var __cards:Array;
		private var __progress:ProgressManager;
		
		
		public function saveAs(value:File):void
		{
			var bytes:ByteArray = __pdf.save(Method.LOCAL);
			
			var fs:FileStream = new FileStream();  
				fs.open( value, FileMode.WRITE);   
				fs.writeBytes(bytes);   
				fs.close();   
			
			value.openWithDefaultApplication();
		}
		
		public function fill(cards:Array):void
		{
			__count = __index = 0;
			__cards = cards;
			
			computeSizes();
			
			next();
		}
		
		private function next():void
		{
			__progress.setProgress(__index, __cards.length);
			if (__index >= __cards.length)
			{
				dispatchEvent(new Event(FILL_COMPLETE));
				return;
			}
			
			var card:Card = __cards[__index] as Card;
			
			if (!card.count)
			{
				doNext();
				return;
			}
			
			card.addEventListener(Card.PREPARED, onCardPrepared);
			card.prepareForPrint();
		}
		
		protected function onCardPrepared(event:Event):void
		{
			var card:Card = event.target as Card;
				card.removeEventListener(Card.PREPARED, onCardPrepared);
			
			for (var i:int=0;i< card.count;i++)
			{
				addCard(__count, card);
				__count++;
			}
			
			doNext();
		}	
		
		private function doNext():void
		{
			__index++;
			next();
		}
		
		private function addCard(i:int, card:Card):void
		{
			if (i % 9 == 0)
			{
				__pdf.addPage(newPage);
				drawLines();
			}
			
			var x:Number = __contentRectangle.x + ((i % 3) * __cardWidth);
			var y:Number = __contentRectangle.y + (Math.floor((i%9)/3) * __cardHeight);
			__pdf.addImageStream(card.byteArray, ColorSpace.DEVICE_RGB,null,x,y,__cardWidth, __cardHeight);
		}
		
		private function computeSizes():void
		{
			var page:Page = newPage;
			
			__dpi = page.w / page.size.mmSize[0];
			__cardWidth = Card.SIZE_WIDTH_MM * __dpi;
			__cardHeight = Card.SIZE_HEIGHT_MM * __dpi
				
			__contentRectangle = new Rectangle;
			__contentRectangle.width = __cardWidth * 3;
			__contentRectangle.x = (page.w - __contentRectangle.width)/2;
			__contentRectangle.height = __cardHeight *3;
			__contentRectangle.y = (page.h - __contentRectangle.height)/2;
		}		
		
		private function get newPage():Page
		{
			return new Page(Orientation.PORTRAIT, Unit.MM, Size.A4);
		}
		
		private function drawLines():void
		{
			var offset:Number = 10;
			
			var r:Rectangle = __contentRectangle;
			
			var w:Number = r.width/3;
			var h:Number = r.height/3;
			
			var i:int;
			var x:Number;
			var y:Number;
			
			for (i=0;i< 4;i++)
			{
				x = r.x + (i*w); 
				__pdf.drawLine(x,r.y -offset,x,r.y);
				__pdf.drawLine(x,r.y +r.height,x,r.y + r.height + offset);
			}
			
			for (i=0;i< 4;i++)
			{
				y = r.y + (i*h); 
				__pdf.drawLine(r.x - offset, y, r.x, y);
				__pdf.drawLine(r.x + r.width, y, r.x +r.width + offset, y);
			}
		}
	}
}